/*
 * PBoostTimerChangeObj.h
 *
 *  Created on: Apr 1, 2015
 *      Author: yuliang
 */

#ifndef PBOOSTTIMERCHANGEOBJ_H_
#define PBOOSTTIMERCHANGEOBJ_H_

#include "PBoostLocalDate.h"
#include <unordered_set>
#include <functional>

template<typename T>
class CPBoostTimerChangeObj {
	typedef std::unordered_set<T*>			SetObj_t;
public:
	typedef std::function<void(T*)>			TimeChangeFunc_t;
	typedef std::function<void()>			TimeEndFunc_t;
	typedef std::vector<int32_t>			VecHourCount_t;
public:
	CPBoostTimerChangeObj(BoostTimer_t* timer)
		: m_ChangeTimer(timer),
		  m_IntervalTime(600),
		  m_DateInfo(nullptr),
		  m_HourCount(VecHourCount_t(24, 0)) {}
	~CPBoostTimerChangeObj() { }
	inline void SetChangeFunc(TimeChangeFunc_t change) { m_ChangeFunc = change; }
	inline void SetEndFunc(TimeEndFunc_t end) { m_EndFunc = end; }
	inline VecHourCount_t* GetHourCount() { return &m_HourCount; }
	inline void SetIntervalTime(uint32_t time) { if (time != 0) m_IntervalTime = time; }

	inline void StartTimer();
	inline void ChangeObj(T* obj) { m_ChangeObj.insert(obj); }
	inline void ChangeAll() { changeObj(-1); }
private:
	void onChange();
	void changeObj(uint32_t count);
private:
	BoostTimer_t*						m_ChangeTimer;
	uint32_t							m_IntervalTime;
	const CPUtility::VecDateInfo_t*		m_DateInfo;
	VecHourCount_t						m_HourCount;
	SetObj_t							m_ChangeObj;

	TimeChangeFunc_t					m_ChangeFunc;
	TimeEndFunc_t						m_EndFunc;
};

template<typename T>
void CPBoostTimerChangeObj<T>::StartTimer() {
	m_ChangeTimer->expires_from_now(boost::posix_time::seconds(m_IntervalTime));
	m_ChangeTimer->async_wait(boost::bind(&CPBoostTimerChangeObj::onChange, this));
}

template<typename T>
void CPBoostTimerChangeObj<T>::onChange() {
	if (!m_ChangeObj.empty()) {
		m_DateInfo = CPBoostLocalDate::GetInstance()->GetCurrentDate();
		int32_t tCount = m_HourCount[m_DateInfo->at(CPUtility::HourFlag)];
		if (tCount > 0)
			changeObj(tCount);
	}
	StartTimer();
}

template<typename T>
void CPBoostTimerChangeObj<T>::changeObj(uint32_t count) {
	do {
		typename SetObj_t::iterator tIter = m_ChangeObj.begin();
		if (tIter != m_ChangeObj.end()) {
			T* tObj = *tIter;
			m_ChangeObj.erase(tIter);
			m_ChangeFunc(tObj);
		} else
			break;
	} while (--count);
	m_EndFunc();
}

#endif /* PBOOSTTIMERCHANGEOBJ_H_ */
